package com.oig.sys.base.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.oig.common.constants.CommonEnum;
import com.oig.common.exception.BadRequestException;
import com.oig.common.module.SysPageInfo;
import com.oig.common.module.SysRequest;
import com.oig.sys.base.dao.ITbCustomsDao;
import com.oig.sys.base.dto.CustomsDto;
import com.oig.sys.base.entity.TbCustoms;
import com.oig.sys.base.service.ITbCustomsService;
import com.oig.sys.base.vo.CustomsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wuxl
 */
@Slf4j
@Service
public class TbCustomsServiceImpl implements ITbCustomsService {

	private final ITbCustomsDao tbCustomsDao;

	@Autowired
	public TbCustomsServiceImpl( ITbCustomsDao tbCustomsDao){
		 this.tbCustomsDao = tbCustomsDao;
	}

	@Transactional
	@Override
	public CustomsVo addTbCustoms(CustomsDto customsDto) {
		TbCustoms customs = this.tbCustomsDao.getByCustomsCode(customsDto.getCustomsCode()) ;
		if (customs!=null) {
			throw new BadRequestException("海关编码重复") ;
		}
		customs = this.tbCustomsDao.getByCustomsName(customsDto.getCustomsName());
		if (customs!=null){
			throw new BadRequestException("海关名称重复") ;
		}
		customs = new TbCustoms();
		BeanUtils.copyProperties(customsDto,customs);
		customs.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbCustomsDao.save(customs) ;
		return this.buildVo(customs);
	}

	private CustomsVo buildVo(TbCustoms customs){
		CustomsVo customsVo = new CustomsVo();
		BeanUtils.copyProperties(customs, customsVo);
		return customsVo;
	}

	@Transactional
	@Override
	public CustomsVo updateTbCustoms(CustomsDto customsDto) {
		TbCustoms customs = this.tbCustomsDao.getTbCustomsById(customsDto.getId()) ;
		if (customs==null) {
			throw new BadRequestException("记录不存在") ;
		}
		TbCustoms customs1 = this.tbCustomsDao.getByCustomsCodeAndIdExits(customsDto.getCustomsCode(),customs.getId());
		if (customs1!=null){
			throw new BadRequestException("海关编码重复") ;
		}
		if (!customs.getCustomsName().equals(customsDto.getCustomsName())){
			customs1 = this.tbCustomsDao.getByCustomsName(customsDto.getCustomsName());
			if (customs1!=null){
				throw new BadRequestException("海关名称重复") ;
			}
		}
		BeanUtils.copyProperties(customsDto, customs,"id", "status");
		this.tbCustomsDao.save(customs) ;
		CustomsVo customsVo = new CustomsVo();
		BeanUtils.copyProperties(customs, customsVo);
		return customsVo;
	}

	@Transactional
	@Override
	public CustomsVo cancelTbCustoms(Integer id) {
		TbCustoms customs = this.tbCustomsDao.getTbCustomsById(id) ;
		if (customs==null) {
			throw new BadRequestException("记录不存在") ;
		}
		if (CommonEnum.CommonStatusEnum.DEL.getCode().equals(customs.getStatus())){
			throw new BadRequestException("已是删除状态") ;
		}
		customs.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		this.tbCustomsDao.save(customs) ;
		return this.buildVo(customs);
	}

	@Override
	public SysPageInfo<CustomsVo> findCustoms(SysRequest<CustomsDto> customsRequest) {
		Pageable pageable = customsRequest.pageable();
		Page<TbCustoms> page ;
		if (customsRequest.getParamDto()!=null){
			Specification<TbCustoms> specification = new Specification<TbCustoms>() {
				@Override
				@Nullable
				public Predicate toPredicate(@NonNull Root<TbCustoms> root, @NonNull CriteriaQuery<?> criteriaQuery, @NonNull CriteriaBuilder criteriaBuilder) {
					List<Predicate> predicateList = new ArrayList<>();
					if (StrUtil.isNotBlank(customsRequest.getParamDto().getStatus())) {
						log.debug("status:{}",customsRequest.getParamDto().getStatus());
						Path<String> statusPath = root.get("status");
						predicateList.add(criteriaBuilder.equal(statusPath, customsRequest.getParamDto().getStatus()));
					} else {
						Path<String> statusPath = root.get("status");
						predicateList.add(criteriaBuilder.equal(statusPath, CommonEnum.CommonStatusEnum.OK.getCode()));
					}
					if (StrUtil.isNotBlank(customsRequest.getParamDto().getSearchWord())) {
						String searchWord = "%" + customsRequest.getParamDto().getSearchWord() + "%";
						Path<String> customsCodePath = root.get("customsCode");
						Path<String> customsNamePath = root.get("customsName");
						predicateList.add(criteriaBuilder.or(criteriaBuilder.like(customsCodePath, searchWord),
								criteriaBuilder.like(customsNamePath, searchWord)));
					}

					if (StrUtil.isNotBlank(customsRequest.getParamDto().getCustomsCode())) {
						Path<String> customsCodePath = root.get("customsCode");
						predicateList.add(criteriaBuilder.equal(customsCodePath, customsRequest.getParamDto().getCustomsCode()));
					}
					if (StrUtil.isNotBlank(customsRequest.getParamDto().getCustomsName())) {
						Path<String> customsNamePath = root.get("customsName");
						predicateList.add(criteriaBuilder.like(customsNamePath, "%" + customsRequest.getParamDto().getCustomsName() + "%"));
					}
					if (StrUtil.isNotBlank(customsRequest.getParamDto().getCityCode())) {
						Path<String> cityCodePath = root.get("cityCode");
						predicateList.add(criteriaBuilder.equal(cityCodePath, customsRequest.getParamDto().getCityCode()));
					}
					criteriaQuery.where(predicateList.toArray(new Predicate[0]));
					return criteriaQuery.getRestriction();
				}
			};
			page = this.tbCustomsDao.findAll(specification, pageable);
		} else {
			page = this.tbCustomsDao.findAll(pageable);
		}
		List<CustomsVo> customsVoList = new ArrayList<>();
		for (TbCustoms customs : page.getContent()){
			CustomsVo customsVo = new CustomsVo();
			BeanUtils.copyProperties(customs, customsVo);
			customsVoList.add(customsVo);
		}
		SysPageInfo<CustomsVo> sysPageInfo = new SysPageInfo<>(customsRequest.getPageNo(), customsRequest.getPageSize(), page.getTotalElements());
		sysPageInfo.setList(customsVoList);
		return sysPageInfo;
	}


	@Override
	public CustomsVo getByName(String name) {
		TbCustoms customs = this.tbCustomsDao.getByCustomsName(name) ;
		if (customs==null) return null;
		return this.buildVo(customs);
	}

	@Override
	public CustomsVo getByOldCode(String oldCode) {
		TbCustoms customs = this.tbCustomsDao.getByOldCode(oldCode) ;
		if (customs==null) return null;
		return this.buildVo(customs);
	}

	@Override
	public CustomsVo getByCode(String code) {
		TbCustoms customs = this.tbCustomsDao.getByCustomsCode(code) ;
		if (customs==null) return null;
		return this.buildVo(customs);
	}

	@Override
	public List<CustomsVo> getByPortCode(String portCode) {
		List<TbCustoms> customsList = this.tbCustomsDao.getByPortCode(portCode);
		List<CustomsVo> customsVoList = new ArrayList<>();
		if(CollectionUtil.isNotEmpty(customsList)){
			for(TbCustoms customs : customsList){
				customsVoList.add(this.buildVo(customs));
			}
		}
		return customsVoList;
	}
}
